import pickle
import os
import sys
import threading
import time
from uuid import uuid4
import zmq
from mdwrkapi import MajorDomoWorker
from mdcliapi import MajorDomoClient

from zhelpers import zpipe

TITANIC_DIR = ".titanic"


def request_filename(suuid):
    return os.path.join(TITANIC_DIR, "%s.req" % suuid)


def reply_filename(suuid):
    return os.path.join(TITANIC_DIR, "%s.rep" % suuid)


def titanic_request(pipe, verbose):
    worker = MajorDomoWorker("tcp://localhost:5555", b"titanic.request", verbose)
    reply = None

    while True:
        request = worker.recv(reply)
        if not request:
            break

        if not os.path.exists(TITANIC_DIR):
            os.mkdir(TITANIC_DIR)

        suuid = uuid4().hex
        filename = request_filename(suuid)
        with open(filename, 'wb') as f:
            pickle.dump(request, f)

        pipe.send_string(suuid)

        reply = [b"200", suuid.encode('utf-8')]


def titanic_reply(verbose):
    worker = MajorDomoWorker("tcp://localhost:5555", b"titanic.reply", verbose)
    reply = None

    while True:
        request = worker.recv(reply)
        if not request:
            break

        suuid = request.pop(0).decode('utf-8')
        req_filename = request_filename(suuid)
        rep_filename = reply_filename(suuid)
        if os.path.exists(rep_filename):
            with open(rep_filename, 'rb') as f:
                reply = pickle.load(f)
            reply = [b"200"] + reply
        else:
            if os.path.exists(req_filename):
                reply = [b"300"]
            else:
                reply = [b"400"]


def titanic_close(verbose):
    worker = MajorDomoWorker("tcp://localhost:5555", b"titanic.close", verbose)
    reply = None

    while True:
        request = worker.recv(reply)
        if not request:
            break

        suuid = request.pop(0).decode('utf-8')
        req_filename = request_filename(suuid)
        rep_filename = reply_filename(suuid)
        if os.path.exists(req_filename):
            os.remove(req_filename)
        if os.path.exists(rep_filename):
            os.remove(rep_filename)
        reply = [b"200"]


def service_success(client, suuid):
    filename = request_filename(suuid)

    if not os.path.exists(filename):
        return True

    with open(filename, 'rb') as f:
        request = pickle.load(f)
    serivce = request.pop(0)
    mmi_request = [serivce]
    mmi_reply = client.send(b"mmi.service", mmi_request)
    service_ok = mmi_reply and mmi_reply[0] == b"200"

    if service_ok:
        reply = client.send(serivce, request)
        if reply:
            filename = reply_filename(suuid)
            with open(filename, "wb") as f:
                pickle.dump(reply, f)
            return True

    return False


def main():
    verbose = '-v' in sys.argv
    ctx = zmq.Context()

    client = MajorDomoClient("tcp://localhost:5555", verbose)
    client.timeout = 1000
    client.retries = 1

    request_pip, peer = zpipe(ctx)
    request_thread = threading.Thread(target=titanic_request, args=(peer, verbose))
    request_thread.daemon = True
    request_thread.start()
    reply_thread = threading.Thread(target=titanic_reply, args=(verbose,))
    reply_thread.daemon = True
    reply_thread.start()
    close_thread = threading.Thread(target=titanic_close, args=(verbose,))
    close_thread.daemon = True
    close_thread.start()

    poller = zmq.Poller()
    poller.register(request_pip, zmq.POLLIN)

    queue_filename = os.path.join(TITANIC_DIR, 'queue')

    while True:
        if not os.path.exists(TITANIC_DIR):
            os.mkdir(TITANIC_DIR)
            f = open(queue_filename, 'wb')
            f.close()
        try:
            items = poller.poll(1000)
        except KeyboardInterrupt:
            break

        if items:
            suuid = request_pip.recv().decode('utf-8')
            with open(queue_filename, 'ab') as f:
                line = "-%s\n" % suuid
                f.write(line.encode('utf-8'))

        with open(queue_filename, 'rb+') as f:
            for entry in f.readlines():
                entry = entry.decode('utf-8')
                if entry[0] == '-':
                    suuid = entry[1:].rstrip()
                    print("I: processing request %s" % suuid)
                    if service_success(client, suuid):
                        here = f.tell()
                        f.seek(-1*len(entry), os.SEEK_CUR)
                        f.write('+'.encode('utf-8'))
                        f.seek(here, os.SEEK_SET)


if __name__ == '__main__':
    main()
